#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
UI组件设置
负责界面布局和控件创建
"""

import os
import sys
import datetime
import tkinter as tk
from tkinter import ttk, filedialog
from pathlib import Path
from typing import Dict, Any
from .themes import ThemedUIComponents
try:
    from PIL import Image, ImageTk
    PIL_AVAILABLE = True
except ImportError:
    PIL_AVAILABLE = False


class UIComponents(ThemedUIComponents):
    """UI组件混入类"""
    
    def setup_ui(self):
        """设置用户界面"""
        self.root.title("西红柿轰炸机专用")
        self.root.geometry("820x720")
        self.root.resizable(True, True)
        self.root.minsize(800, 600)
        
        # 初始化主题系统
        self.init_theme()
        
        main_paned = ttk.PanedWindow(self.root, orient=tk.VERTICAL)
        main_paned.pack(fill=tk.BOTH, expand=True, padx=15, pady=15)
        
        top_frame = ttk.Frame(main_paned)
        main_paned.add(top_frame, weight=4)
        
        log_frame = ttk.LabelFrame(main_paned, text="📋 操作日志", padding="5")
        main_paned.add(log_frame, weight=1)
        
        top_frame.columnconfigure(1, weight=1)
        
        self.setup_log_area(log_frame)
        
        # 在日志区域创建后设置程序图标
        self._set_window_icon()
        
        ttk.Label(top_frame, text="📁 扫描路径:").grid(row=0, column=0, sticky=tk.W, pady=(5, 10))
        
        path_frame = ttk.Frame(top_frame)
        path_frame.grid(row=0, column=1, columnspan=2, sticky=(tk.W, tk.E), pady=(5, 10))
        path_frame.columnconfigure(0, weight=1)
        
        self.path_var = tk.StringVar(value=str(Path.home()))
        self.path_entry = ttk.Entry(path_frame, textvariable=self.path_var, font=('Segoe UI', 9))
        self.path_entry.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 8))
        
        ttk.Button(path_frame, text="📂 浏览", command=self.browse_folder).grid(row=0, column=1)
        
        button_frame = ttk.Frame(top_frame)
        button_frame.grid(row=1, column=0, columnspan=3, pady=(10, 15))
        
        ttk.Button(button_frame, text="🗂️ 扫描临时文件", command=self.scan_temp).pack(side=tk.LEFT, padx=6)
        ttk.Button(button_frame, text="🔄 查找重复文件", command=self.scan_duplicates).pack(side=tk.LEFT, padx=6)
        ttk.Button(button_frame, text="📊 查找大文件", command=self.scan_large).pack(side=tk.LEFT, padx=6)
        ttk.Button(button_frame, text="💻 检测开发目录", command=self.scan_dev_dirs).pack(side=tk.LEFT, padx=6)
        ttk.Button(button_frame, text="🎨 切换主题", command=self.switch_theme).pack(side=tk.LEFT, padx=12)
        
        option_frame = ttk.Frame(top_frame)
        option_frame.grid(row=2, column=0, columnspan=3, pady=(5, 10), sticky=(tk.W, tk.E))
        option_frame.columnconfigure(0, weight=1)
        
        self.status_var = tk.StringVar(value="🟢 就绪")
        status_label = ttk.Label(option_frame, textvariable=self.status_var, font=('Segoe UI', 9))
        status_label.grid(row=0, column=0, sticky=tk.W)
        
        self.progress = ttk.Progressbar(option_frame, mode='determinate', length=250)
        self.progress.grid(row=0, column=1, sticky=tk.E, padx=(10, 0))
        
        self.notebook = ttk.Notebook(top_frame)
        self.notebook.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(15, 10))
        top_frame.rowconfigure(3, weight=1)
        
        self.temp_frame = ttk.Frame(self.notebook)
        self.dup_frame = ttk.Frame(self.notebook)
        self.large_frame = ttk.Frame(self.notebook)
        self.dev_frame = ttk.Frame(self.notebook)
        
        self.notebook.add(self.temp_frame, text="临时文件")
        self.notebook.add(self.dup_frame, text="重复文件")
        self.notebook.add(self.large_frame, text="大文件")
        self.notebook.add(self.dev_frame, text="开发目录")
        
        self.notebook.bind("<<NotebookTabChanged>>", self.on_tab_changed)
        
        self.setup_file_lists()
        
        # 应用默认主题
        self.apply_theme()
    
    def setup_log_area(self, log_frame):
        """设置日志区域"""
        log_frame.columnconfigure(0, weight=1)
        log_frame.rowconfigure(0, weight=1)
        
        self.log_text = tk.Text(log_frame, height=4, wrap=tk.WORD, 
                               font=('Consolas', 9), bg='#f8f9fa', fg='#2d3748')
        log_scroll = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
        self.log_text.configure(yscrollcommand=log_scroll.set)
        
        self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        log_scroll.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
        log_button_frame = ttk.Frame(log_frame)
        log_button_frame.grid(row=1, column=0, columnspan=2, sticky=tk.W, pady=(5, 0))
        ttk.Button(log_button_frame, text="清空日志", command=self.clear_log).pack(side=tk.LEFT)
        
        # 日志标签颜色将在apply_theme()中设置

    def setup_file_lists(self):
        """设置文件列表"""
        frames = [
            ('temp', self.temp_frame, "临时文件列表 (双击打开位置)"),
            ('dup', self.dup_frame, "重复文件列表 (双击打开位置)"),
            ('large', self.large_frame, "大文件列表 (双击打开位置)"),
            ('dev', self.dev_frame, "开发目录列表 (双击打开位置)")
        ]
        
        for name, frame, title in frames:
            frame.columnconfigure(0, weight=1)
            frame.rowconfigure(0, weight=1)
            
            tree = ttk.Treeview(frame, selectmode='extended')
            scrollbar = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=tree.yview)
            tree.configure(yscrollcommand=scrollbar.set)
            
            tree.bind('<Button-1>', lambda event, tree_ref=tree: self.on_tree_click(event, tree_ref))
            tree.bind('<Double-1>', lambda event, tree_ref=tree: self.on_file_double_click(event, tree_ref))
            
            if name == 'large':
                tree['columns'] = ('check', 'size', 'count')
                tree.heading('#0', text='文件夹/文件 (双击打开位置)', command=lambda tree_ref=tree, col='#0', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.heading('check', text='☐', command=lambda tree_ref=tree: self.toggle_all_selection(tree_ref))
                tree.heading('size', text='大小 ↕', command=lambda tree_ref=tree, col='size', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.heading('count', text='文件数 ↕', command=lambda tree_ref=tree, col='count', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.column('check', width=30, minwidth=30)
                tree.column('size', width=100)
                tree.column('count', width=60)
            elif name == 'dev':
                tree['columns'] = ('check', 'type', 'size')
                tree.heading('#0', text='目录路径 (双击打开位置)', command=lambda tree_ref=tree, col='#0', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.heading('check', text='☐', command=lambda tree_ref=tree: self.toggle_all_selection(tree_ref))
                tree.heading('type', text='项目类型/路径 ↕', command=lambda tree_ref=tree, col='type', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.heading('size', text='大小 ↕', command=lambda tree_ref=tree, col='size', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.column('check', width=30, minwidth=30)
                tree.column('type', width=400)
                tree.column('size', width=100)
            else:
                tree['columns'] = ('check', 'info')
                tree.heading('#0', text=title, command=lambda tree_ref=tree, col='#0', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.heading('check', text='☐', command=lambda tree_ref=tree: self.toggle_all_selection(tree_ref))
                tree.heading('info', text='路径/详细信息 ↕', command=lambda tree_ref=tree, col='info', tree_name=name: self.sort_treeview(tree_ref, col, tree_name))
                tree.column('check', width=30, minwidth=30)
                tree.column('info', width=300)
            
            tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
            scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
            
            button_frame = ttk.Frame(frame)
            button_frame.grid(row=1, column=0, columnspan=2, sticky=tk.W, pady=(5, 0))
            
            self.delete_btn = ttk.Button(button_frame, text="🗑️ 批量删除选中项", 
                      command=lambda tree_ref=tree: self.delete_selected())
            self.delete_btn.pack(side=tk.LEFT, padx=5)
            
            ttk.Button(button_frame, text="☑️ 全选", 
                      command=lambda tree_ref=tree: self.toggle_all_selection(tree_ref)).pack(side=tk.LEFT, padx=5)
            
            # 为不同类型添加分类筛选
            if name == 'dev':
                self.setup_dev_filter(button_frame)
            elif name == 'temp':
                self.setup_temp_filter(button_frame)
            elif name == 'large':
                self.setup_large_filter(button_frame)
            
            setattr(self, f'{name}_tree', tree)

    def setup_dev_filter(self, button_frame):
        """设置开发目录筛选控件"""
        # 添加分隔符
        ttk.Separator(button_frame, orient='vertical').pack(side=tk.LEFT, padx=10, fill=tk.Y)
        
        # 筛选标签
        ttk.Label(button_frame, text="🔍 分类筛选:").pack(side=tk.LEFT, padx=(10, 5))
        
        # 分类筛选下拉菜单
        self.dev_filter_var = tk.StringVar(value="全部显示")
        self.dev_filter_combo = ttk.Combobox(button_frame, textvariable=self.dev_filter_var, 
                                           width=15, state="readonly")
        
        # 筛选选项
        filter_options = [
            "全部显示",
            "📁 代码目录", 
            "🔨 构建输出", 
            "💾 缓存目录", 
            "📄 日志文件",
            "📚 文档目录", 
            "⚙️ 配置文件", 
            "📦 依赖包", 
            "📄 根目录文件",
            "📋 其他目录"
        ]
        self.dev_filter_combo['values'] = filter_options
        self.dev_filter_combo.pack(side=tk.LEFT, padx=5)
        
        # 绑定筛选事件
        self.dev_filter_combo.bind('<<ComboboxSelected>>', self.on_dev_filter_changed)
        
        # 项目类型筛选
        ttk.Label(button_frame, text="项目类型:").pack(side=tk.LEFT, padx=(10, 5))
        self.project_type_filter_var = tk.StringVar(value="全部项目")
        self.project_type_filter_combo = ttk.Combobox(button_frame, textvariable=self.project_type_filter_var,
                                                    width=12, state="readonly")
        self.project_type_filter_combo['values'] = ["全部项目"]
        self.project_type_filter_combo.pack(side=tk.LEFT, padx=5)
        self.project_type_filter_combo.bind('<<ComboboxSelected>>', self.on_dev_filter_changed)

    def browse_folder(self):
        """浏览文件夹"""
        folder = filedialog.askdirectory(initialdir=self.path_var.get())
        if folder:
            self.path_var.set(folder)

    def update_progress(self, value):
        """更新进度条"""
        self.progress['value'] = value
        self.root.update_idletasks()

    def update_status(self, status_text):
        """更新状态文本"""
        self.status_var.set(status_text)
        self.root.update_idletasks()

    def add_log(self, message: str, level: str = 'info'):
        """添加日志"""
        timestamp = datetime.datetime.now().strftime("[%H:%M:%S]")
        log_entry = f"{timestamp} {message}\n"
        
        self.log_text.insert(tk.END, log_entry, level)
        self.log_text.see(tk.END)
        self.root.update_idletasks()

    def clear_log(self):
        """清空日志"""
        self.log_text.delete(1.0, tk.END)
        self.add_log("日志已清空", 'info')


    def check_admin_privileges(self):
        """检查管理员权限"""
        try:
            import ctypes
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False

    def _handle_permission_error(self, operation, error_msg):
        """处理权限错误"""
        self.status_var.set("权限错误")
        self.progress['value'] = 0
        self.add_log(f"[ERROR] {operation}失败: {error_msg}", 'error')
        
        if not self.check_admin_privileges():
            self.add_log("[HINT] 建议以管理员身份运行程序以获得完整权限", 'warning')

    def _handle_scan_error(self, operation, error_msg):
        """处理扫描错误"""
        self.status_var.set("扫描出错")
        self.progress['value'] = 0
        self.add_log(f"[ERROR] {operation}出现错误: {error_msg}", 'error')

    def _update_temp_results(self, temp_files):
        """更新临时文件扫描结果"""
        # 内存保护：限制最大文件数量
        if len(temp_files) > 10000:
            self.add_log(f"[WARN] 发现{len(temp_files)}个临时文件，为保护性能只显示前10000个", 'warning')
            temp_files = temp_files[:10000]
        
        self.current_scan_data['temp'] = temp_files
        # 存储原始数据用于筛选
        self.temp_original_data = temp_files
        
        for item in self.temp_tree.get_children():
            self.temp_tree.delete(item)
        
        if not temp_files:
            self.status_var.set("未发现临时文件")
            self.progress['value'] = 100
            self.add_log("[OK] 未发现任何临时文件", 'success')
            return
        
        file_tree = self.core.build_file_tree(temp_files)
        total_files = self._populate_tree(self.temp_tree, file_tree, '')
        
        total_size = 0
        for file_path in temp_files:
            try:
                total_size += os.path.getsize(file_path)
            except:
                pass
        
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"发现 {len(temp_files)} 个临时文件，共 {size_str}")
        self.progress['value'] = 100
        self.add_log(f"[OK] 发现 {len(temp_files)} 个临时文件，总大小: {size_str}", 'success')
        
        # 自动切换到临时文件标签页
        self.notebook.select(0)

    def _populate_tree(self, tree_widget, file_tree: Dict[str, Any], parent_id: str) -> int:
        """填充树形控件"""
        total_files = 0
        max_expand_level = getattr(self, 'default_expand_levels', 2)
        
        def get_current_level(item_id):
            level = 0
            current = item_id
            while current:
                current = tree_widget.parent(current)
                if current:
                    level += 1
            return level
        
        # 获取父路径（避免重复计算）
        parent_path = self._get_parent_path(tree_widget, parent_id) if parent_id else ""
        
        for key, value in sorted(file_tree.items()):
            if isinstance(value, dict):
                # 对于文件夹，在info列显示文件夹路径
                folder_path = key if not parent_path else os.path.join(parent_path, key)
                folder_id = tree_widget.insert(parent_id, 'end', text=key, 
                                             values=('☐', folder_path), 
                                             tags=(key,))
                
                current_level = get_current_level(folder_id)
                if current_level < max_expand_level:
                    tree_widget.item(folder_id, open=True)
                
                subfolder_files = self._populate_tree(tree_widget, value, folder_id)
                total_files += subfolder_files
                
                # 更新info列显示文件数和路径
                tree_widget.set(folder_id, 'info', f'{folder_path} ({subfolder_files} 个文件)')
            else:
                # 对于文件，value就是完整路径，直接在info列显示
                file_id = tree_widget.insert(parent_id, 'end', text=key,
                                           values=('☐', value), 
                                           tags=(value,))
                total_files += 1
        
        return total_files

    def _get_parent_path(self, tree_widget, item_id):
        """获取树节点的完整路径"""
        if not item_id:
            return ""
        
        path_parts = []
        current = item_id
        while current:
            text = tree_widget.item(current)['text']
            path_parts.append(text)
            current = tree_widget.parent(current)
        
        # 反转列表并连接路径
        path_parts.reverse()
        return os.path.join(*path_parts) if path_parts else ""


    def _update_dup_results(self, duplicates):
        """更新重复文件扫描结果"""
        self.current_scan_data['dup'] = duplicates
        # 存储原始数据用于筛选
        self.dup_original_data = duplicates
        
        for item in self.dup_tree.get_children():
            self.dup_tree.delete(item)
        
        if not duplicates:
            self.status_var.set("未发现重复文件")
            self.progress['value'] = 100
            self.add_log("[OK] 未发现重复文件", 'success')
            return
        
        total_files = 0
        total_size = 0
        group_index = 1
        
        for hash_val, file_list in duplicates.items():
            if len(file_list) > 1:
                group_name = f"重复组 {group_index} ({len(file_list)} 个文件)"
                group_id = self.dup_tree.insert('', 'end', text=group_name, 
                                              values=('☐', f'{len(file_list)} 个重复文件'),
                                              tags=('duplicate_group',))
                
                file_size = 0
                try:
                    file_size = os.path.getsize(file_list[0])
                    total_size += file_size * (len(file_list) - 1)
                except:
                    pass
                
                for file_path in file_list:
                    file_name = os.path.basename(file_path)
                    file_id = self.dup_tree.insert(group_id, 'end', text=file_name,
                                                 values=('☐', file_path), 
                                                 tags=(file_path,))
                    total_files += 1
                
                self.dup_tree.item(group_id, open=True)
                group_index += 1
        
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"发现 {len(duplicates)} 组重复文件，可释放 {size_str}")
        self.progress['value'] = 100
        self.add_log(f"[OK] 发现 {len(duplicates)} 组重复文件，共 {total_files} 个，可释放空间: {size_str}", 'success')
        
        # 默认按名称升序排列，让重复组有序显示
        self.sort_treeview(self.dup_tree, '#0', 'dup')
        
        # 自动切换到重复文件标签页
        self.notebook.select(1)

    def _update_large_results(self, large_files):
        """更新大文件扫描结果"""
        self.current_scan_data['large'] = large_files
        # 存储原始数据用于筛选
        self.large_original_data = large_files
        
        for item in self.large_tree.get_children():
            self.large_tree.delete(item)
        
        if not large_files:
            self.status_var.set("未发现大文件")
            self.progress['value'] = 100
            self.add_log("[OK] 未发现大文件 (>50MB)", 'success')
            return
        
        for file_path, file_size in large_files:
            file_name = os.path.basename(file_path)
            
            if file_size > 1024 * 1024 * 1024:
                size_str = f"{file_size / 1024 / 1024 / 1024:.1f} GB"
            elif file_size > 1024 * 1024:
                size_str = f"{file_size / 1024 / 1024:.1f} MB"
            else:
                size_str = f"{file_size / 1024:.1f} KB"
            
            # 在文件名中显示简短名称，在大小列后显示完整路径
            self.large_tree.insert('', 'end', text=f"{file_name} ({file_path})",
                                 values=('☐', size_str, '1'),
                                 tags=(file_path,))
        
        total_size = sum(size for _, size in large_files)
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"发现 {len(large_files)} 个大文件，共 {size_str}")
        self.progress['value'] = 100
        self.add_log(f"[OK] 发现 {len(large_files)} 个大文件，总大小: {size_str}", 'success')
        
        # 默认按大小降序排列
        self.sort_treeview(self.large_tree, 'size', 'large')
        
        # 自动切换到大文件标签页
        self.notebook.select(2)

    def _update_dev_results(self, dev_dirs):
        """更新开发目录扫描结果"""
        self.current_scan_data['dev'] = dev_dirs
        # 存储原始数据用于筛选
        self.dev_original_data = dev_dirs
        
        for item in self.dev_tree.get_children():
            self.dev_tree.delete(item)
        
        if not dev_dirs:
            self.status_var.set("未发现开发目录")
            self.progress['value'] = 100
            self.add_log("[OK] 未发现开发目录", 'success')
            return
        
        # 按项目类型分组
        project_types = {}
        for dir_path, project_type, dir_size, content_analysis in dev_dirs:
            if project_type not in project_types:
                project_types[project_type] = []
            project_types[project_type].append((dir_path, dir_size, content_analysis))
        
        # 分类名称映射
        category_names = {
            'code': '📁 代码目录',
            'build': '🔨 构建输出',
            'cache': '💾 缓存目录',
            'logs': '📄 日志文件',
            'docs': '📚 文档目录',
            'config': '⚙️ 配置文件',
            'deps': '📦 依赖包',
            'other': '📋 其他目录',
            'root_files': '📄 根目录文件'
        }
        
        for project_type, dirs in project_types.items():
            type_total_size = sum(size for _, size, _ in dirs)
            
            if type_total_size > 1024 * 1024 * 1024:
                type_size_str = f"{type_total_size / 1024 / 1024 / 1024:.1f} GB"
            elif type_total_size > 1024 * 1024:
                type_size_str = f"{type_total_size / 1024 / 1024:.1f} MB"
            else:
                type_size_str = f"{type_total_size / 1024:.1f} KB"
            
            # 创建项目类型根节点
            type_id = self.dev_tree.insert('', 'end', text=f"🚀 {project_type} 项目",
                                         values=('☐', f'{len(dirs)} 个项目', type_size_str),
                                         tags=('project_type_group',))
            
            # 为每个项目创建子节点
            for dir_path, dir_size, content_analysis in dirs:
                dir_name = os.path.basename(dir_path)
                
                if dir_size > 1024 * 1024 * 1024:
                    size_str = f"{dir_size / 1024 / 1024 / 1024:.1f} GB"
                elif dir_size > 1024 * 1024:
                    size_str = f"{dir_size / 1024 / 1024:.1f} MB"
                else:
                    size_str = f"{dir_size / 1024:.1f} KB"
                
                # 创建项目节点，显示完整路径
                project_id = self.dev_tree.insert(type_id, 'end', text=f"📁 {dir_name}",
                                               values=('☐', f"{project_type} | {dir_path}", size_str),
                                               tags=(dir_path,))
                
                # 计算所有分类的总大小用于验证
                total_categorized_size = sum(data['size'] for data in content_analysis.values())
                size_diff = dir_size - total_categorized_size
                if abs(size_diff) > 1024 * 1024:  # 如果差异大于1MB就显示
                    if size_diff > 0:
                        diff_str = f" (可能有 {size_diff / 1024 / 1024:.1f} MB 未分类)"
                    else:
                        diff_str = f" (分类统计可能有重复)"
                else:
                    diff_str = ""
                
                # 更新项目节点显示，包含差异信息
                self.dev_tree.set(project_id, 'type', f"{project_type} | {dir_path}{diff_str}")
                
                # 为每个项目添加分类子节点
                for category, data in content_analysis.items():
                    if data['folders']:  # 只显示有内容的分类
                        category_size = data['size']
                        category_count = data['count']
                        
                        if category_size > 1024 * 1024 * 1024:
                            cat_size_str = f"{category_size / 1024 / 1024 / 1024:.1f} GB"
                        elif category_size > 1024 * 1024:
                            cat_size_str = f"{category_size / 1024 / 1024:.1f} MB"
                        elif category_size > 1024:
                            cat_size_str = f"{category_size / 1024:.1f} KB"
                        else:
                            cat_size_str = f"{category_size} B"
                        
                        # 创建分类节点
                        category_display_name = category_names.get(category, f"📋 {category}")
                        category_id = self.dev_tree.insert(project_id, 'end',
                                                         text=f"{category_display_name} ({len(data['folders'])} 项)",
                                                         values=('☐', f'{category_count} 个文件', cat_size_str),
                                                         tags=('category_group',))
                        
                        # 为分类添加具体的文件夹
                        for folder_info in data['folders']:
                            folder_name = folder_info['name']
                            folder_path = folder_info['path']
                            folder_size = folder_info['size']
                            folder_count = folder_info['count']
                            
                            if folder_size > 1024 * 1024 * 1024:
                                folder_size_str = f"{folder_size / 1024 / 1024 / 1024:.1f} GB"
                            elif folder_size > 1024 * 1024:
                                folder_size_str = f"{folder_size / 1024 / 1024:.1f} MB"
                            elif folder_size > 1024:
                                folder_size_str = f"{folder_size / 1024:.1f} KB"
                            else:
                                folder_size_str = f"{folder_size} B"
                            
                            self.dev_tree.insert(category_id, 'end', text=f"{folder_name}",
                                               values=('☐', f'{folder_count} 个文件 | {folder_path}', folder_size_str),
                                               tags=(folder_path,))
                
                # 展开项目节点但不展开分类节点
                self.dev_tree.item(project_id, open=True)
            
            # 展开项目类型节点
            self.dev_tree.item(type_id, open=True)
        
        total_size = sum(size for _, _, size, _ in dev_dirs)
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"发现 {len(dev_dirs)} 个开发目录，共 {size_str}")
        self.progress['value'] = 100
        self.add_log(f"[OK] 发现 {len(dev_dirs)} 个开发目录，总大小: {size_str}，已分类显示", 'success')
        
        # 更新项目类型筛选选项并重置筛选状态
        self.update_project_type_filter_options(dev_dirs)
        self.reset_filter_states()
        
        # 默认按大小降序排列
        self.sort_treeview(self.dev_tree, 'size', 'dev')
        
        # 自动切换到开发目录标签页
        self.notebook.select(3)

    def update_project_type_filter_options(self, dev_dirs):
        """更新项目类型筛选选项"""
        if not hasattr(self, 'project_type_filter_combo'):
            return
            
        # 收集所有项目类型
        project_types = set()
        for dir_path, project_type, dir_size, content_analysis in dev_dirs:
            project_types.add(project_type)
        
        # 更新下拉菜单选项
        options = ["全部项目"] + sorted(list(project_types))
        self.project_type_filter_combo['values'] = options

    def on_dev_filter_changed(self, event=None):
        """处理开发目录筛选变化"""
        if not hasattr(self, 'dev_original_data') or not self.dev_original_data:
            self.add_log("[WARN] 请先扫描开发目录后再使用筛选功能", 'warning')
            return
        
        # 获取筛选条件
        category_filter = self.dev_filter_var.get()
        project_type_filter = self.project_type_filter_var.get()
        
        # 应用筛选
        filtered_data = self.filter_dev_results(self.dev_original_data, category_filter, project_type_filter)
        
        # 重新显示筛选后的结果
        self.display_filtered_dev_results(filtered_data)

    def filter_dev_results(self, dev_dirs, category_filter, project_type_filter):
        """筛选开发目录结果"""
        if category_filter == "全部显示" and project_type_filter == "全部项目":
            return dev_dirs
        
        filtered_dirs = []
        
        # 分类名称映射（去掉图标）
        category_map = {
            "📁 代码目录": "code",
            "🔨 构建输出": "build", 
            "💾 缓存目录": "cache",
            "📄 日志文件": "logs",
            "📚 文档目录": "docs",
            "⚙️ 配置文件": "config",
            "📦 依赖包": "deps",
            "📄 根目录文件": "root_files",
            "📋 其他目录": "other"
        }
        
        target_category = category_map.get(category_filter)
        
        for dir_path, project_type, dir_size, content_analysis in dev_dirs:
            # 项目类型筛选
            if project_type_filter != "全部项目" and project_type != project_type_filter:
                continue
            
            # 分类筛选
            if category_filter == "全部显示":
                filtered_dirs.append((dir_path, project_type, dir_size, content_analysis))
            elif target_category:
                # 检查该项目是否包含目标分类
                if target_category in content_analysis and content_analysis[target_category]['folders']:
                    # 只保留目标分类的数据
                    filtered_content = {
                        target_category: content_analysis[target_category]
                    }
                    # 重新计算大小（只包含筛选的分类）
                    filtered_size = content_analysis[target_category]['size']
                    filtered_dirs.append((dir_path, project_type, filtered_size, filtered_content))
        
        return filtered_dirs

    def display_filtered_dev_results(self, filtered_dirs):
        """显示筛选后的开发目录结果"""
        # 清空当前显示
        for item in self.dev_tree.get_children():
            self.dev_tree.delete(item)
        
        if not filtered_dirs:
            self.status_var.set("筛选后无结果")
            self.add_log("[INFO] 筛选后没有匹配的开发目录", 'info')
            return
        
        # 重新组织数据并显示
        project_types = {}
        for dir_path, project_type, dir_size, content_analysis in filtered_dirs:
            if project_type not in project_types:
                project_types[project_type] = []
            project_types[project_type].append((dir_path, dir_size, content_analysis))
        
        # 分类名称映射
        category_names = {
            'code': '📁 代码目录',
            'build': '🔨 构建输出',
            'cache': '💾 缓存目录',
            'logs': '📄 日志文件',
            'docs': '📚 文档目录',
            'config': '⚙️ 配置文件',
            'deps': '📦 依赖包',
            'other': '📋 其他目录',
            'root_files': '📄 根目录文件'
        }
        
        # 显示筛选后的结果（复用原有的显示逻辑）
        for project_type, dirs in project_types.items():
            type_total_size = sum(size for _, size, _ in dirs)
            
            if type_total_size > 1024 * 1024 * 1024:
                type_size_str = f"{type_total_size / 1024 / 1024 / 1024:.1f} GB"
            elif type_total_size > 1024 * 1024:
                type_size_str = f"{type_total_size / 1024 / 1024:.1f} MB"
            else:
                type_size_str = f"{type_total_size / 1024:.1f} KB"
            
            # 创建项目类型根节点
            type_id = self.dev_tree.insert('', 'end', text=f"🚀 {project_type} 项目",
                                         values=('☐', f'{len(dirs)} 个项目', type_size_str),
                                         tags=('project_type_group',))
            
            # 为每个项目创建子节点
            for dir_path, dir_size, content_analysis in dirs:
                dir_name = os.path.basename(dir_path)
                
                if dir_size > 1024 * 1024 * 1024:
                    size_str = f"{dir_size / 1024 / 1024 / 1024:.1f} GB"
                elif dir_size > 1024 * 1024:
                    size_str = f"{dir_size / 1024 / 1024:.1f} MB"
                else:
                    size_str = f"{dir_size / 1024:.1f} KB"
                
                # 创建项目节点
                project_id = self.dev_tree.insert(type_id, 'end', text=f"📁 {dir_name}",
                                               values=('☐', f"{project_type} | {dir_path}", size_str),
                                               tags=(dir_path,))
                
                # 为每个项目添加分类子节点
                for category, data in content_analysis.items():
                    if data['folders']:  # 只显示有内容的分类
                        category_size = data['size']
                        category_count = data['count']
                        
                        if category_size > 1024 * 1024 * 1024:
                            cat_size_str = f"{category_size / 1024 / 1024 / 1024:.1f} GB"
                        elif category_size > 1024 * 1024:
                            cat_size_str = f"{category_size / 1024 / 1024:.1f} MB"
                        elif category_size > 1024:
                            cat_size_str = f"{category_size / 1024:.1f} KB"
                        else:
                            cat_size_str = f"{category_size} B"
                        
                        # 创建分类节点
                        category_display_name = category_names.get(category, f"📋 {category}")
                        category_id = self.dev_tree.insert(project_id, 'end',
                                                         text=f"{category_display_name} ({len(data['folders'])} 项)",
                                                         values=('☐', f'{category_count} 个文件', cat_size_str),
                                                         tags=('category_group',))
                        
                        # 为分类添加具体的文件夹
                        for folder_info in data['folders']:
                            folder_name = folder_info['name']
                            folder_path = folder_info['path']
                            folder_size = folder_info['size']
                            folder_count = folder_info['count']
                            
                            if folder_size > 1024 * 1024 * 1024:
                                folder_size_str = f"{folder_size / 1024 / 1024 / 1024:.1f} GB"
                            elif folder_size > 1024 * 1024:
                                folder_size_str = f"{folder_size / 1024 / 1024:.1f} MB"
                            elif folder_size > 1024:
                                folder_size_str = f"{folder_size / 1024:.1f} KB"
                            else:
                                folder_size_str = f"{folder_size} B"
                            
                            self.dev_tree.insert(category_id, 'end', text=f"{folder_name}",
                                               values=('☐', f'{folder_count} 个文件 | {folder_path}', folder_size_str),
                                               tags=(folder_path,))
                
                # 展开项目节点但不展开分类节点
                self.dev_tree.item(project_id, open=True)
            
            # 展开项目类型节点
            self.dev_tree.item(type_id, open=True)
        
        # 更新状态
        total_size = sum(size for _, _, size, _ in filtered_dirs)
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"筛选显示 {len(filtered_dirs)} 个开发目录，共 {size_str}")
        self.add_log(f"[INFO] 筛选显示 {len(filtered_dirs)} 个开发目录，总大小: {size_str}", 'info')

    def setup_temp_filter(self, button_frame):
        """设置临时文件筛选控件"""
        ttk.Separator(button_frame, orient='vertical').pack(side=tk.LEFT, padx=10, fill=tk.Y)
        
        ttk.Label(button_frame, text="🔍 文件类型:").pack(side=tk.LEFT, padx=(10, 5))
        
        self.temp_filter_var = tk.StringVar(value="全部类型")
        self.temp_filter_combo = ttk.Combobox(button_frame, textvariable=self.temp_filter_var, 
                                            width=12, state="readonly")
        
        filter_options = [
            "全部类型",
            "🗂️ 临时文件(.tmp/.temp)",
            "📄 日志文件(.log)", 
            "💾 缓存文件(.cache)",
            "📋 备份文件(.bak/.old)",
            "🔧 编辑临时文件(.swp/.swo)",
            "📁 其他临时文件"
        ]
        self.temp_filter_combo['values'] = filter_options
        self.temp_filter_combo.pack(side=tk.LEFT, padx=5)
        self.temp_filter_combo.bind('<<ComboboxSelected>>', self.on_temp_filter_changed)

    def setup_large_filter(self, button_frame):
        """设置大文件筛选控件"""
        ttk.Separator(button_frame, orient='vertical').pack(side=tk.LEFT, padx=10, fill=tk.Y)
        
        ttk.Label(button_frame, text="🔍 文件类型:").pack(side=tk.LEFT, padx=(10, 5))
        
        self.large_filter_var = tk.StringVar(value="全部类型")
        self.large_filter_combo = ttk.Combobox(button_frame, textvariable=self.large_filter_var, 
                                             width=12, state="readonly")
        
        filter_options = [
            "全部类型",
            "🎬 视频文件",
            "🖼️ 图片文件", 
            "📦 压缩文件",
            "💿 程序文件(.exe/.dll)",
            "📚 文档文件",
            "📁 其他文件"
        ]
        self.large_filter_combo['values'] = filter_options
        self.large_filter_combo.pack(side=tk.LEFT, padx=5)
        self.large_filter_combo.bind('<<ComboboxSelected>>', self.on_large_filter_changed)

    def on_temp_filter_changed(self, event=None):
        """处理临时文件筛选变化"""
        if not hasattr(self, 'temp_original_data') or not self.temp_original_data:
            self.add_log("[WARN] 请先扫描临时文件后再使用筛选功能", 'warning')
            return
        
        filter_type = self.temp_filter_var.get()
        filtered_files = self.filter_temp_files(self.temp_original_data, filter_type)
        self.display_filtered_temp_results(filtered_files)

    def on_large_filter_changed(self, event=None):
        """处理大文件筛选变化"""
        if not hasattr(self, 'large_original_data') or not self.large_original_data:
            self.add_log("[WARN] 请先扫描大文件后再使用筛选功能", 'warning')
            return
        
        filter_type = self.large_filter_var.get()
        filtered_files = self.filter_large_files(self.large_original_data, filter_type)
        self.display_filtered_large_results(filtered_files)

    def filter_temp_files(self, temp_files, filter_type):
        """筛选临时文件"""
        if filter_type == "全部类型":
            return temp_files
        
        filtered = []
        for file_path in temp_files:
            file_ext = os.path.splitext(file_path)[1].lower()
            
            if filter_type == "🗂️ 临时文件(.tmp/.temp)":
                if file_ext in ['.tmp', '.temp', '.~tmp']:
                    filtered.append(file_path)
            elif filter_type == "📄 日志文件(.log)":
                if file_ext in ['.log'] or 'log' in os.path.basename(file_path).lower():
                    filtered.append(file_path)
            elif filter_type == "💾 缓存文件(.cache)":
                if file_ext in ['.cache'] or 'cache' in os.path.basename(file_path).lower():
                    filtered.append(file_path)
            elif filter_type == "📋 备份文件(.bak/.old)":
                if file_ext in ['.bak', '.old', '.backup']:
                    filtered.append(file_path)
            elif filter_type == "🔧 编辑临时文件(.swp/.swo)":
                if file_ext in ['.swp', '.swo', '.swn']:
                    filtered.append(file_path)
            elif filter_type == "📁 其他临时文件":
                # 其他不在上述分类中的文件
                common_exts = {'.tmp', '.temp', '.~tmp', '.log', '.cache', '.bak', '.old', '.backup', '.swp', '.swo', '.swn'}
                if file_ext not in common_exts and not ('log' in os.path.basename(file_path).lower() or 'cache' in os.path.basename(file_path).lower()):
                    filtered.append(file_path)
        
        return filtered

    def filter_large_files(self, large_files, filter_type):
        """筛选大文件"""
        if filter_type == "全部类型":
            return large_files
        
        filtered = []
        for file_path, file_size in large_files:
            file_ext = os.path.splitext(file_path)[1].lower()
            
            if filter_type == "🎬 视频文件":
                video_exts = {'.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', '.m4v', '.3gp'}
                if file_ext in video_exts:
                    filtered.append((file_path, file_size))
            elif filter_type == "🖼️ 图片文件":
                image_exts = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.svg', '.webp', '.raw'}
                if file_ext in image_exts:
                    filtered.append((file_path, file_size))
            elif filter_type == "📦 压缩文件":
                archive_exts = {'.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz', '.cab', '.iso'}
                if file_ext in archive_exts:
                    filtered.append((file_path, file_size))
            elif filter_type == "💿 程序文件(.exe/.dll)":
                program_exts = {'.exe', '.dll', '.msi', '.deb', '.rpm', '.dmg', '.app'}
                if file_ext in program_exts:
                    filtered.append((file_path, file_size))
            elif filter_type == "📚 文档文件":
                doc_exts = {'.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.rtf'}
                if file_ext in doc_exts:
                    filtered.append((file_path, file_size))
            elif filter_type == "📁 其他文件":
                # 其他不在上述分类中的文件
                known_exts = {'.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', '.m4v', '.3gp',
                             '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.svg', '.webp', '.raw',
                             '.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz', '.cab', '.iso',
                             '.exe', '.dll', '.msi', '.deb', '.rpm', '.dmg', '.app',
                             '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.rtf'}
                if file_ext not in known_exts:
                    filtered.append((file_path, file_size))
        
        return filtered

    def display_filtered_temp_results(self, filtered_files):
        """显示筛选后的临时文件结果"""
        for item in self.temp_tree.get_children():
            self.temp_tree.delete(item)
        
        if not filtered_files:
            self.status_var.set("筛选后无临时文件")
            self.add_log("[INFO] 筛选后没有匹配的临时文件", 'info')
            return
        
        # 构建文件树并显示
        file_tree = self.core.build_file_tree(filtered_files)
        total_files = self._populate_tree(self.temp_tree, file_tree, '')
        
        # 计算总大小
        total_size = 0
        for file_path in filtered_files:
            try:
                total_size += os.path.getsize(file_path)
            except:
                pass
        
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"筛选显示 {len(filtered_files)} 个临时文件，共 {size_str}")
        self.add_log(f"[INFO] 筛选显示 {len(filtered_files)} 个临时文件，总大小: {size_str}", 'info')

    def display_filtered_large_results(self, filtered_files):
        """显示筛选后的大文件结果"""
        for item in self.large_tree.get_children():
            self.large_tree.delete(item)
        
        if not filtered_files:
            self.status_var.set("筛选后无大文件")
            self.add_log("[INFO] 筛选后没有匹配的大文件", 'info')
            return
        
        # 显示筛选后的大文件
        for file_path, file_size in filtered_files:
            file_name = os.path.basename(file_path)
            
            if file_size > 1024 * 1024 * 1024:
                size_str = f"{file_size / 1024 / 1024 / 1024:.1f} GB"
            elif file_size > 1024 * 1024:
                size_str = f"{file_size / 1024 / 1024:.1f} MB"
            else:
                size_str = f"{file_size / 1024:.1f} KB"
            
            self.large_tree.insert('', 'end', text=f"{file_name} ({file_path})",
                                 values=('☐', size_str, '1'),
                                 tags=(file_path,))
        
        # 计算总大小
        total_size = sum(size for _, size in filtered_files)
        if total_size > 1024 * 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
        elif total_size > 1024 * 1024:
            size_str = f"{total_size / 1024 / 1024:.1f} MB"
        else:
            size_str = f"{total_size / 1024:.1f} KB"
        
        self.status_var.set(f"筛选显示 {len(filtered_files)} 个大文件，共 {size_str}")
        self.add_log(f"[INFO] 筛选显示 {len(filtered_files)} 个大文件，总大小: {size_str}", 'info')

    def reset_filter_states(self):
        """重置所有筛选状态到默认值"""
        if hasattr(self, 'dev_filter_var'):
            self.dev_filter_var.set("全部显示")
        if hasattr(self, 'project_type_filter_var'):
            self.project_type_filter_var.set("全部项目")
        if hasattr(self, 'temp_filter_var'):
            self.temp_filter_var.set("全部类型")
        if hasattr(self, 'large_filter_var'):
            self.large_filter_var.set("全部类型")

    def _set_window_icon(self):
        """设置窗口图标和任务栏图标"""
        try:
            icon_path = self._get_icon_path()
            if not icon_path:
                return
            
            self._set_app_id()
            ico_path = self._create_ico_file(icon_path)
            
            if ico_path:
                self._set_iconbitmap(ico_path)
                self._set_iconphoto(icon_path)
                self._set_windows_api_icon(ico_path)
            
            self.add_log("[SUCCESS] 图标设置操作完成", 'success')
            
        except Exception as e:
            self.add_log(f"[ERROR] 图标设置失败: {e}", 'error')

    def _get_icon_path(self):
        """获取图标文件路径"""
        if hasattr(sys, '_MEIPASS'):
            icon_path = os.path.join(sys._MEIPASS, 'icon.jpg')
        else:
            base_dir = os.path.dirname(os.path.dirname(__file__))
            icon_path = os.path.join(base_dir, 'assets', 'icon.jpg')
            if not os.path.exists(icon_path):
                icon_path = os.path.join(base_dir, 'icon.jpg')
        
        if not os.path.exists(icon_path):
            self.add_log("[WARNING] 图标文件未找到，使用默认图标", 'warning')
            return None
        
        return icon_path

    def _set_app_id(self):
        """设置应用程序ID"""
        if os.name == 'nt':
            try:
                import ctypes
                app_id = "TomatoBomber.FileCleanerTool.1.0"
                ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(app_id)
                self.add_log(f"[DEBUG] 设置应用程序ID成功: {app_id}", 'info')
            except Exception as e:
                self.add_log(f"[DEBUG] 设置应用程序ID失败: {e}", 'warning')

    def _create_ico_file(self, icon_path):
        """创建ICO文件"""
        if not PIL_AVAILABLE:
            return None
            
        try:
            img = Image.open(icon_path)
            src_dir = os.path.dirname(__file__)
            ico_path = os.path.join(src_dir, 'app_icon.ico')
            
            sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
            img_resized = img.resize((256, 256), Image.Resampling.LANCZOS)
            img_resized.save(ico_path, 'ICO', sizes=sizes)
            
            self.add_log(f"[DEBUG] ICO文件创建成功: {ico_path}", 'info')
            return ico_path
            
        except Exception as e:
            self.add_log(f"[DEBUG] PIL图标处理失败: {e}", 'error')
            return None

    def _set_iconbitmap(self, ico_path):
        """使用iconbitmap设置任务栏图标"""
        try:
            self.root.iconbitmap(ico_path)
            self.add_log("[DEBUG] iconbitmap设置成功", 'success')
        except Exception as e:
            self.add_log(f"[DEBUG] iconbitmap设置失败: {e}", 'warning')

    def _set_iconphoto(self, icon_path):
        """使用iconphoto设置窗口图标"""
        if not PIL_AVAILABLE:
            return
            
        try:
            img = Image.open(icon_path)
            sizes = [16, 24, 32, 48, 64]
            photos = []
            
            for size in sizes:
                img_resized = img.resize((size, size), Image.Resampling.LANCZOS)
                photo = ImageTk.PhotoImage(img_resized)
                photos.append(photo)
            
            self.root.iconphoto(True, *photos)
            self.root._icon_photos = photos  # 保持引用
            self.add_log("[DEBUG] iconphoto设置成功", 'info')
            
        except Exception as e:
            self.add_log(f"[DEBUG] iconphoto设置失败: {e}", 'warning')

    def _set_windows_api_icon(self, ico_path):
        """使用Windows API设置图标"""
        if os.name != 'nt':
            return
            
        try:
            import ctypes
            self.root.update_idletasks()
            hwnd = self.root.winfo_id()
            
            icon_sizes = [(16, 16), (32, 32), (48, 48)]
            for width, height in icon_sizes:
                hicon = ctypes.windll.user32.LoadImageW(
                    0, ico_path, 1, width, height, 0x00000010 | 0x00000040)
                
                if hicon:
                    icon_type = 0 if width <= 16 else 1  # ICON_SMALL or ICON_LARGE
                    ctypes.windll.user32.SendMessageW(hwnd, 0x0080, icon_type, hicon)
            
            # 刷新任务栏
            ctypes.windll.user32.RedrawWindow(hwnd, None, None, 0x0001 | 0x0004)
            self.add_log("[DEBUG] Windows API图标设置完成", 'success')
            
        except Exception as e:
            self.add_log(f"[DEBUG] Windows API图标设置失败: {e}", 'warning')
    
    def sort_treeview(self, tree, column, tree_name):
        """对TreeView进行排序"""
        try:
            # 获取当前排序状态
            current_sort = self.sort_states[tree_name]
            
            # 如果点击的是同一列，则反转排序顺序
            if current_sort['column'] == column:
                current_sort['reverse'] = not current_sort['reverse']
            else:
                current_sort['column'] = column
                current_sort['reverse'] = False
            
            # 更新列标题显示排序方向
            self._update_column_headers(tree, tree_name, column, current_sort['reverse'])
            
            # 获取所有顶级项目
            items = list(tree.get_children())
            if not items:
                return
            
            # 根据列类型进行排序
            if column == 'size':
                # 按大小排序
                items.sort(key=lambda item: self._get_size_sort_key(tree, item), 
                          reverse=current_sort['reverse'])
            elif column == 'count':
                # 按文件数排序
                items.sort(key=lambda item: self._get_count_sort_key(tree, item), 
                          reverse=current_sort['reverse'])
            elif column == '#0':
                # 按名称排序
                items.sort(key=lambda item: tree.item(item)['text'].lower(), 
                          reverse=current_sort['reverse'])
            elif column == 'info':
                # 按详细信息排序
                items.sort(key=lambda item: tree.set(item, 'info'), 
                          reverse=current_sort['reverse'])
            elif column == 'type':
                # 按项目类型排序
                items.sort(key=lambda item: tree.set(item, 'type'), 
                          reverse=current_sort['reverse'])
            
            # 重新排列项目
            for index, item in enumerate(items):
                tree.move(item, '', index)
            
            self.add_log(f"[INFO] 已按 {column} 列进行{'降序' if current_sort['reverse'] else '升序'}排序", 'info')
            
        except Exception as e:
            self.add_log(f"[ERROR] 排序失败: {str(e)}", 'error')
    
    def _update_column_headers(self, tree, tree_name, sorted_column, reverse):
        """更新列标题以显示排序状态"""
        try:
            # 获取TreeView的所有列
            columns = ['#0'] + list(tree['columns'])
            
            # 排序方向指示符
            sort_indicator = ' ↓' if reverse else ' ↑'
            
            for col in columns:
                if col == 'check':  # 跳过复选框列
                    continue
                    
                # 获取原始标题文本（去除之前的排序指示符）
                current_text = tree.heading(col)['text']
                base_text = current_text.replace(' ↑', '').replace(' ↓', '').replace(' ↕', '')
                
                if col == sorted_column:
                    # 当前排序列显示方向指示符
                    new_text = base_text + sort_indicator
                else:
                    # 其他列显示双向箭头
                    new_text = base_text + ' ↕'
                
                tree.heading(col, text=new_text)
                
        except Exception as e:
            self.add_log(f"[ERROR] 更新列标题失败: {str(e)}", 'error')
    
    def _get_size_sort_key(self, tree, item):
        """获取大小排序键值"""
        try:
            size_text = tree.set(item, 'size')
            if not size_text:
                return 0
            
            # 解析大小文本 (例如: "1.5 GB", "234 MB", "56 KB")
            parts = size_text.split()
            if len(parts) >= 2:
                value = float(parts[0])
                unit = parts[1].upper()
                
                # 转换为字节数
                multipliers = {
                    'B': 1,
                    'KB': 1024,
                    'MB': 1024 * 1024,
                    'GB': 1024 * 1024 * 1024,
                    'TB': 1024 * 1024 * 1024 * 1024
                }
                
                return value * multipliers.get(unit, 1)
            return 0
        except:
            return 0
    
    def _get_count_sort_key(self, tree, item):
        """获取文件数排序键值"""
        try:
            count_text = tree.set(item, 'count')
            if not count_text:
                return 0
            
            # 解析文件数文本 (例如: "150", "1", "25 个文件")
            if '个文件' in count_text:
                return int(count_text.split()[0])
            elif '个项目' in count_text:
                return int(count_text.split()[0])
            elif count_text.isdigit():
                return int(count_text)
            return 0
        except:
            return 0
    
    def get_tree_by_name(self, name):
        """根据名称获取对应的树控件"""
        tree_map = {
            'temp': getattr(self, 'temp_tree', None),
            'dup': getattr(self, 'dup_tree', None),
            'large': getattr(self, 'large_tree', None),
            'dev': getattr(self, 'dev_tree', None)
        }
        return tree_map.get(name)